#!/usr/bin/env python3

# Copyright © 2025 Wenze Wei
#
# This file is part of Pisces L1.
#
# Licensed under the Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC 4.0).
# You may not use this file except in compliance with the License.
# Commercial use is strictly prohibited.
# You may obtain a copy of the License at
#
#     https://creativecommons.org/licenses/by-nc/4.0/
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys
import platform
import subprocess

def setup(args):
    """
    Auto setup virtual environment and install requirements if needed, then auto-enter the virtual environment shell.

    Args:
        args: Arguments passed to the function, currently not used in the function.
    """
    # Print a message indicating the start of the auto-environment setup
    print("✅\tPisces auto environment setup...")
    # Get the path of the current Python executable
    py_exec = sys.executable
    # Define the directory path for the virtual environment
    venv_dir = os.path.join(os.getcwd(), "pisces_env")
    # Check if the current operating system is Windows
    is_windows = platform.system().lower().startswith("win")

    # Check if the script is not running inside a virtual environment
    if sys.prefix == sys.base_prefix:
        print("✅\tNot in virtual environment. Creating venv...")
        # Create a new virtual environment
        subprocess.check_call([py_exec, "-m", "venv", venv_dir])
        print(f"✅\tVirtual environment created at {venv_dir}")
        # Get the path of the Python executable inside the virtual environment
        python_bin = os.path.join(venv_dir, "Scripts" if is_windows else "bin", "python" + (".exe" if is_windows else ""))
        print("✅\tRe-running setup in venv...")
        # Re-run the script using the Python executable inside the virtual environment
        os.execv(python_bin, [python_bin] + sys.argv)
        return
    else:
        print("✅\tAlready in virtual environment.")

    # Upgrade the pip package manager to the latest version
    print("✅\tUpgrading pip...")
    subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip"])

    # Install the required packages listed in requirements.txt
    print("✅\tInstalling requirements.txt...")
    subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])
    print("✅\tPisces environment setup complete!")

    # Auto-enter the virtual environment shell
    if is_windows:
        # Get the path of the Windows command shell
        shell = os.environ.get("COMSPEC", "cmd.exe")
        # Check if the current shell is PowerShell
        if "powershell.exe" in shell.lower() or "pwsh.exe" in shell.lower():
            # Get the path of the PowerShell activation script
            activate = os.path.join(venv_dir, "Scripts", "Activate.ps1")
            print("✅\tAuto-entering Pisces venv shell (PowerShell)...")
            # Start PowerShell and activate the virtual environment
            os.execv(shell, [shell, "-NoExit", "-Command", f". '{activate}'"])
        else:
            # Get the path of the cmd activation script
            activate = os.path.join(venv_dir, "Scripts", "activate.bat")
            print("✅\tAuto-entering Pisces venv shell (Windows cmd)...")
            # Start cmd and activate the virtual environment
            os.execv(shell, [shell, "/K", activate])
    else:
        # Get the path of the Unix-like shell
        shell = os.environ.get("SHELL", "/bin/bash")
        # Get the path of the activation script
        activate = os.path.join(venv_dir, "bin", "activate")
        print("✅\tAuto-entering Pisces venv shell (Linux/Mac)...")
        # Start the shell and activate the virtual environment
        os.execv(shell, [shell, "-i", "-c", f"source '{activate}'; exec {shell}"])